package main

import (
	"fmt"
	"strconv"
	"strings"
	"unicode"
)

var ApiFile string

var Register = `
var _{{a}} {{b}}

type {{b}} interface {
    {{list1}}
}

type Unim{{b}} struct {
}

{{list5}}

func {{b}}_Register(m {{b}}) {

    _{{a}} = m

	{{list3}}
}
`

var Logic_Outer_Register_List = `
    msg.RegisterHandler({{m1}}, {{p1}}, {{p2}},_{{b}}_{{h}}_{{c1}}_{{c2}})
`

var Logic_Inner_Register_List = `
    msg.RegisterInner({{m1}}, {{p1}}, {{p2}},_{{b}}_{{h}}_{{c1}}_{{c2}})
`

var Logic_Rpc_Register_List = `
	msg.RegisterRpc({{m1}}, {{p1}}, {{p2}},_{{b}}_{{h}}_{{c1}}_{{c2}})
`

var Mothod = `
    //{{$C}}
    {{h}}(msg.IMsgContext,{{p1}}) bool 
`

var Implemented = `
//{{$C}}
func (*Unim{{b}}) {{h}}(context msg.IMsgContext, _ {{p1}}) bool {
	println("{{b}}.{{h}} not implemented")
	return false
}
`

var Handle = `
func _{{b}}_{{h}}_{{c1}}_{{c2}}(context msg.IMsgContext, msg interface{}) bool {
    if _{{a}} == nil {
    	fmt.Println(" not register _{{a}}.{{h}} ")
        return false
    }
    data := msg.(*{{p1}})
    return _{{a}}.{{h}}(context, data) 
}
`

type Temple struct {
	method        string
	register_head string
	register_list string
	handle_list   string
	implement     string
}

var templeList map[string]*Temple

var HandleHead = `
//--------------------
// auto build by tools  DO NOT EDIT
//--------------------

package api

import (
	"fmt"
	"towerdefence/src/pkg/msg"
	"towerdefence/src/proto/pb/pb"
)

`

func Atoi(str string) int {
	i, err := strconv.Atoi(str)
	if err != nil {
		return 0
	}
	return i
}

func InitTemple() {
	templeList = make(map[string]*Temple)
	ApiFile = HandleHead
	t := &Temple{}
	t.register_head = Register
	t.method = Mothod
	t.implement = Implemented
	t.handle_list = Handle
	templeList["all"] = t
}

func build_method(temple *Temple, RealfunName, cmd1, cmd2, param, reparam, a_string, b_string, comment string) (string, string, string, string, string, string) {
	var p2 string
	if reparam == "NULL" {
		p2 = "nil"
	} else {
		p2 = "&pb." + reparam + "{}"
	}

	m := strings.ReplaceAll(temple.method, "{{h}}", RealfunName)
	m = strings.ReplaceAll(m, "{{p1}}", "*pb."+param)
	m = strings.ReplaceAll(m, "{{$C}}", comment)

	im := strings.ReplaceAll(temple.implement, "{{h}}", RealfunName)
	im = strings.ReplaceAll(im, "{{b}}", b_string)
	im = strings.ReplaceAll(im, "{{p1}}", "*pb."+param)
	im = strings.ReplaceAll(im, "{{$C}}", comment)

	r := strings.ReplaceAll(Logic_Rpc_Register_List, "{{c1}}", cmd1)
	r = strings.ReplaceAll(r, "{{p1}}", "&pb."+param+"{}")
	r = strings.ReplaceAll(r, "{{p2}}", p2)
	r = strings.ReplaceAll(r, "{{h}}", RealfunName)
	r = strings.ReplaceAll(r, "{{c1}}", cmd1)
	r = strings.ReplaceAll(r, "{{c2}}", cmd2)
	r = strings.ReplaceAll(r, "{{b}}", b_string)

	cmd1Num := Atoi(cmd1)
	cmd2Num := Atoi(cmd2)
	msgValue, ok := MsgDefMap[fmt.Sprintf("%s_%s", b_string, RealfunName)]
	r1 := ""
	if ok {
		r1 = strings.ReplaceAll(Logic_Outer_Register_List, "{{m1}}", fmt.Sprintf("%d", msgValue))
	} else {
		r1 = strings.ReplaceAll(Logic_Outer_Register_List, "{{m1}}", fmt.Sprintf("%d", cmd1Num<<4+cmd2Num))
	}
	r1 = strings.ReplaceAll(r1, "{{c1}}", cmd1)
	r1 = strings.ReplaceAll(r1, "{{p1}}", "&pb."+param+"{}")
	r1 = strings.ReplaceAll(r1, "{{p2}}", p2)
	r1 = strings.ReplaceAll(r1, "{{h}}", RealfunName)
	r1 = strings.ReplaceAll(r1, "{{c1}}", cmd1)
	r1 = strings.ReplaceAll(r1, "{{c2}}", cmd2)
	r1 = strings.ReplaceAll(r1, "{{b}}", b_string)

	r2 := strings.ReplaceAll(Logic_Inner_Register_List, "{{c1}}", cmd1)
	r2 = strings.ReplaceAll(r2, "{{p1}}", "&pb."+param+"{}")
	r2 = strings.ReplaceAll(r2, "{{p2}}", p2)
	r2 = strings.ReplaceAll(r2, "{{h}}", RealfunName)
	r2 = strings.ReplaceAll(r2, "{{c1}}", cmd1)
	r2 = strings.ReplaceAll(r2, "{{c2}}", cmd2)
	r2 = strings.ReplaceAll(r2, "{{b}}", b_string)

	h := strings.ReplaceAll(temple.handle_list, "{{h}}", RealfunName)
	h = strings.ReplaceAll(h, "{{c1}}", cmd1)
	h = strings.ReplaceAll(h, "{{c2}}", cmd2)
	h = strings.ReplaceAll(h, "{{a}}", a_string)
	h = strings.ReplaceAll(h, "{{b}}", b_string)
	h = strings.ReplaceAll(h, "{{p1}}", "pb."+param)
	return m, r, r1, r2, h, im
}

func make_handle(sers []*Service) {
	InitTemple()
	for _, service := range sers {
		if service != nil {
			var tName string
			if unicode.IsUpper([]rune(service.name)[1]) {
				tName = Case2Camel(service.name)
			} else {
				tName = service.name
			}
			a_string := tName + "_XX"
			b_string := tName
			temple, ok := templeList["all"]
			if ok {
				s1 := strings.ReplaceAll(temple.register_head, "{{a}}", a_string)
				s2 := strings.ReplaceAll(s1, "{{b}}", b_string)
				var list1 string
				var list2 string
				var list3 string
				var list4 string
				var list5 string
				var handleList string
				var isIn bool
				for _, mothod := range service.methods {
					if mothod != nil {
						if mothod.typ == 0 || mothod.typ == 1 {
							isIn = true
							var RealfunName string
							//RealfunName := Case2Camel(mothod.name)
							if unicode.IsUpper([]rune(service.name)[1]) {
								RealfunName = Case2Camel(mothod.name)
							} else {
								RealfunName = mothod.name
							}
							cmd1 := fmt.Sprintf("%d", mothod.cmd)
							cmd2 := fmt.Sprintf("%d", mothod.act)
							param := Ucfirst(mothod.input)
							reparam := Ucfirst(mothod.output)
							m, r, r1, r2, h, im := build_method(temple, RealfunName, cmd1, cmd2, param, reparam, a_string, b_string, mothod.comment)
							list1 = list1 + m
							list2 = list2 + r
							list3 = list3 + r1
							list4 = list4 + r2
							list5 = list5 + im
							handleList = handleList + h
						}
					}
				}
				if isIn {
					s3 := strings.ReplaceAll(s2, "{{list1}}", list1)
					s4 := strings.ReplaceAll(s3, "{{list2}}", list2)
					s5 := strings.ReplaceAll(s4, "{{list3}}", list3)
					s6 := strings.ReplaceAll(s5, "{{list4}}", list4)
					s7 := strings.ReplaceAll(s6, "{{list5}}", list5)
					s7 = s7 + handleList
					ApiFile = ApiFile + s7
				}
			}
		}
	}
	err := WriteFile("./api/api.go", []byte(ApiFile))
	if err != nil {
		panic(err)
	}
}
